package com.coocaa.ops.admin.v1.timedtask.job.impl;


import com.coocaa.ops.admin.v1.timedtask.constant.CronConstants;
import com.coocaa.ops.admin.v1.timedtask.convert.TimedTaskQueryConverter;
import com.coocaa.ops.admin.v1.timedtask.job.AbstractQuartzJob;
import com.coocaa.ops.admin.v1.timedtask.job.IJobService;
import com.coocaa.ops.admin.v1.timedtask.job.TimelyShelvesQuartzJob;
import com.coocaa.ops.admin.v1.timedtask.job.listener.*;
import com.coocaa.ops.admin.v1.timedtask.job.util.MyJobUtils;
import com.coocaa.ops.admin.v1.timedtask.model.QuartzSchedulerModel;
import com.coocaa.ops.common.core.biz.timedtask.entity.TimedTaskInfoEntity;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * @author bijiahao
 * @date : 2017/12/18.
 * @description
 */
@Service
public class MyQuartzJobServiceImpl implements IJobService {
    private static final Logger log = LoggerFactory.getLogger(MyQuartzJobServiceImpl.class);

    private final static StdSchedulerFactory SCHEDULER_FACTORY = new StdSchedulerFactory();

    @Override
    public void addTimePointExecOnceQuartzJob(TimedTaskInfoEntity timedTask, Class<? extends AbstractQuartzJob> jobClazz) {
        String jobName = MyJobUtils.getJobName(timedTask);
        String groupName = MyJobUtils.getGroupName(timedTask);
        //定时任务信息
        JobDetail jobDetail = JobBuilder.newJob(jobClazz)
                .withIdentity(jobName, groupName)
                .usingJobData("resourceId", timedTask.getResourceId())
                .usingJobData("resourceType", timedTask.getResourceType())
                .build();
        //定时任务触发器信息
        SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                .forJob(jobName, groupName)
                .withIdentity(MyJobUtils.getTriggerName(timedTask), groupName)
                .startAt(timedTask.getReleaseTime())
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withRepeatCount(0)
                        .withIntervalInMinutes(0)
                )
                .build();
        try {
            Scheduler scheduler = SCHEDULER_FACTORY.getScheduler();
            scheduler.scheduleJob(jobDetail, simpleTrigger);
            if (!scheduler.isShutdown()) {
                scheduler.getListenerManager().addJobListener(new RealTimeOnceJobListener(jobDetail.getKey().getName(), scheduler),
                        this.getJobGroupMatcher(groupName));
                scheduler.getListenerManager().addTriggerListener(new RealTimeOnceTriggerListener(jobDetail.getKey().getName(), scheduler),
                        this.getTriggerGroupMatcher(groupName));
                scheduler.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("===获取任务调度器异常: " + e.getMessage());

        }
    }


    @Override
    public void addJobForTimelyShelves(TimedTaskInfoEntity timedTask, Class<TimelyShelvesQuartzJob> jobClazz) {
        String jobName = MyJobUtils.getJobName(timedTask);
        String groupName = MyJobUtils.getGroupName(timedTask);
        //定时任务信息
        JobDetail jobDetail = JobBuilder.newJob(jobClazz)
                .withIdentity(jobName, groupName)
                .usingJobData("resourceId", timedTask.getResourceId())
                .usingJobData("resourceType", timedTask.getResourceType())
                .usingJobData("resourceVersion", timedTask.getResourceVersion())
                .build();
        //定时任务触发器信息
        SimpleTrigger simpleTrigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                .forJob(jobName, groupName)
                .withIdentity(MyJobUtils.getTriggerName(timedTask), groupName)
                .startAt(timedTask.getReleaseTime())
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                        .withRepeatCount(0)
                        .withIntervalInMinutes(3)
                )
                .build();
        try {
            Scheduler scheduler = SCHEDULER_FACTORY.getScheduler();
            scheduler.scheduleJob(jobDetail, simpleTrigger);
            if (!scheduler.isShutdown()) {
                scheduler.getListenerManager().addJobListener(new TimelyShelvesJobListener(jobDetail.getKey().getName(), scheduler),
                        this.getJobGroupMatcher(groupName));
                scheduler.getListenerManager().addTriggerListener(new TimelyShelvesTriggerListener(jobDetail.getKey().getName(), scheduler),
                        this.getTriggerGroupMatcher(groupName));
                scheduler.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("===获取任务调度器异常: " + e.getMessage());

        }
    }

    @Override
    public void addCronJob(TimedTaskInfoEntity timedTask,  Class<? extends AbstractQuartzJob> jobClazz) {
        String jobName = MyJobUtils.getJobName(timedTask);
        String groupName = MyJobUtils.getGroupName(timedTask);
        //定时任务信息
        JobDetail jobDetail = JobBuilder.newJob(jobClazz)
                .withIdentity(jobName, groupName)
                .usingJobData("resourceId", timedTask.getResourceId())
                .usingJobData("resourceType", timedTask.getResourceType())
                .usingJobData("resourceVersion", timedTask.getResourceVersion())
                .build();
        //定时任务触发器信息
        CronTrigger cronTrigger = TriggerBuilder.newTrigger()
                .forJob(jobName, groupName)
                .withIdentity(MyJobUtils.getTriggerName(timedTask), groupName)
                .withSchedule(CronScheduleBuilder.cronSchedule(StringUtils.isNotBlank(timedTask.getCron()) ? timedTask.getCron() : CronConstants.EVERY_DAY))
                .build();
        try {
            Scheduler scheduler = SCHEDULER_FACTORY.getScheduler();
            scheduler.scheduleJob(jobDetail, cronTrigger);
            if (!scheduler.isShutdown()) {
                scheduler.getListenerManager().addJobListener(new MyCronJobListener(jobDetail.getKey().getName(), scheduler),
                        this.getJobGroupMatcher(groupName));
                scheduler.getListenerManager().addTriggerListener(new MyCronTriggerListener(jobDetail.getKey().getName(), scheduler),
                        this.getTriggerGroupMatcher(groupName));
                scheduler.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("===获取任务调度器异常: " + e.getMessage());

        }
    }


    @Override
    public void delJob(TimedTaskInfoEntity timedTask) {
        try {
            Scheduler scheduler = SCHEDULER_FACTORY.getScheduler();
            scheduler.deleteJob(JobKey.jobKey(MyJobUtils.getJobName(timedTask), MyJobUtils.getGroupName(timedTask)));
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.error("===去除任务异常: " + e.getMessage());
        }
    }

    @Override
    public QuartzSchedulerModel getQuartzSchedulerInfo() throws Exception {
        Scheduler scheduler = SCHEDULER_FACTORY.getScheduler();
        return TimedTaskQueryConverter.getQuartzSchedulerModel(scheduler);
    }

    @Override
    public boolean isJobExist(TimedTaskInfoEntity entity) {
        try {
            Scheduler scheduler = SCHEDULER_FACTORY.getScheduler();
            return scheduler.checkExists(JobKey.jobKey(MyJobUtils.getJobName(entity), MyJobUtils.getGroupName(entity)));
        } catch (SchedulerException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取job组匹配
     *
     * @param group
     * @return
     */
    private GroupMatcher<JobKey> getJobGroupMatcher(String group) {
        GroupMatcher<JobKey> matcher = GroupMatcher.jobGroupEquals(group);
        return matcher;
    }


    /**
     * 获取trigger组匹配
     *
     * @param group
     * @return
     */
    private GroupMatcher<TriggerKey> getTriggerGroupMatcher(String group) {
        GroupMatcher<TriggerKey> matcher = GroupMatcher.triggerGroupEquals(group);
        return matcher;
    }
}
